﻿#include "qpushbox.h"
#include "ui_qpushbox.h"
#include <QPainter>
#include <QPushButton>
#include <QDebug>
#include <dataconfig.h>
#include <iostream>
#include <QKeyEvent>
#include <QMessageBox>
#include <QLabel>
#include <QPoint>
#include <QPen>
#include<QMessageBox>
qpushbox::qpushbox(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::qpushbox)
{
    ui->setupUi(this);
    //默认第一关
    initLevel(minLevel);
    //上一关
    connect(ui->btn_prev,&QPushButton::clicked,this,[=](){
        if(levelindex!=minLevel)
        {
            initLevel(levelindex-1);
            update();
        }
    });
    //下一关
    connect(ui->btn_next,&QPushButton::clicked,this,[=](){
        if(levelindex!=maxLevel)
        {
            initLevel(levelindex+1);
            update();
        }
    });
    //重开
    connect(ui->btn_restart,&QPushButton::clicked,this,[=](){
        initLevel(levelindex);
        update();
    });
    //说明
    connect(ui->btn_explaint,&QPushButton::clicked,this,[=](){
        QString str = "用键盘上的上、下、左、右键移动小人，把箱子全部推到小球的位置即可过关。箱子只可向前推，不能往后拉，并且小人一次只能推动一个箱子";
        QMessageBox::information(this,"游戏说明",str);
    });

}

qpushbox::~qpushbox()
{
    delete ui;
}

void qpushbox::initLevel(int level)
{
    //判断越界
    if(level<minLevel)
        level=minLevel;
    if(level>maxLevel)
        level=maxLevel;
    levelindex = level;
    this->person_position_x = -1;
    this->person_position_y = -1;
    //获胜标志
    isWin = false;
    //人物朝向为下
    hero_stat = DIR_DOWN;
    //移动次数置0
    moveTimes = 0;
    //读取关卡数据
    for(int i=0;i<16;i++){
        for(int j=0;j<16;j++){
            gameArray[i][j] = config.mData[level][j][i];
            posArray[i][j] = config.mData[level][j][i];
        }
    }
}
//判断人物是否能走,并且移动 p1 p2分别是往前一格 两格
bool qpushbox::tryGo(QPoint p1, QPoint p2)
{
    if(posArray[p1.x()][p1.y()]==1){//前面是墙
        return false;
    }
    if(posArray[p1.x()][p1.y()]==3||posArray[p1.x()][p1.y()]==5){//前面是箱子
         //还需判断箱子前面是否有障碍物，箱子或墙
        if(posArray[p2.x()][p2.y()]==1||posArray[p2.x()][p2.y()]==3||posArray[p2.x()][p2.y()]==5)
        {
           return false;
        }
        //若没有 人物前面的箱子前进一步
        posArray[p2.x()][p2.y()]=3;
    }
    //人物前进一格
    posArray[p1.x()][p1.y()]=4;
    //人物移动之后原来的位置变化
    int cur = posArray[this->person_position_x][this->person_position_y];
    if(cur!=2) //不是陷阱
       {
           if(cur==5) //可能是5 既有箱子也有陷阱
           {
               cur=2; //移开还是陷阱
           }
           else
           {
               cur=0; //移开是地板
           }
       }
    //重置小人位置的地图参数
    posArray[this->person_position_x][this->person_position_y]=cur;
    //人物移动了 更新坐标值
    this->person_position_x = p1.x();
    this->person_position_y = p1.y();
    //移动了 返回true
    return true;
}
void qpushbox::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QPixmap pix;
    pix.load(":/images/block.gif");
    //画背景图片
    int d = 35;
    for(int i = 0; i < 16; i++) //画出背景地板
    {
        for(int j = 0; j < 16; j++)
        {
            painter.drawPixmap(d*i, d*j, pix);
        }
    }
    // 画其他的图案
        QString str;
        for(int i = 0 ; i < 16; i++)
        {
            for(int j = 0 ; j < 16 ; j++)
            {
                if(this->posArray[i][j] == 1) //显示墙
                {
                    str = ":/images/wall.png";
                    pix.load(str);
                    painter.drawPixmap(d*i, d*j -11, pix);
                }
                else if(this->posArray[i][j] == 2) //显示陷阱
                {
                    str = ":/images/ball.png";
                    pix.load(str);
                    painter.drawPixmap(d*i +3, d*j +5, pix);
                }
                else if(this->posArray[i][j] == 3) //显示箱子
                {
                    str = ":/images/box.png";
                    pix.load(str);
                    painter.drawPixmap(d*i, d*j -10, pix);
                }
                else if(this->posArray[i][j] == 4) //显示人物
                {
                    this->person_position_x = i;
                    this->person_position_y = j;
                    //画人物
                    if(hero_stat == DIR_UP){
                        str = ":/images/up.png";
                    }else if(hero_stat == DIR_DOWN){
                        str = ":/images/down.png";
                    }else if(hero_stat == DIR_LEFT){
                        str = ":/images/left.png";
                    }else if(hero_stat == DIR_RIGHT){
                        str = ":/images/right.png";
                    }
                    pix.load(str);
                    painter.drawPixmap(d*i -8, d*j -27, pix);
                }
                else if(this->posArray[i][j] == 5) //箱子在陷阱中
                {
                    str = ":/images/box.png";
                    pix.load(str);
                    painter.drawPixmap(d*i, d*j -10, pix);
                }
                else if(this->gameArray[i][j]==2||this->gameArray[i][j]==5)
                {
                    str = ":/images/ball.png";
                    pix.load(str);
                    painter.drawPixmap(d*i +3, d*j +5, pix);
                }
            }
        }
    ui->lb_level->setText(QString("第%1关").arg(levelindex));
    ui->lb_move->setText(QString("移动%1次").arg(moveTimes));
}

void qpushbox::keyReleaseEvent(QKeyEvent *event)
{
    // 如果游戏胜利了 则不反应键盘事件
    if(isWin)
    {
        return QWidget::keyPressEvent(event);
    }
   // 如果是处理两个普通按键，得避免自动重复
   int i = this->person_position_x;
   int j = this->person_position_y;
   // 人物移动逻辑判断
   QPoint p1; //移动方向走一格处
   QPoint p2; //移动方向走两格处
    if(event->key() == Qt::Key_Up) //点击了向上
    {
        hero_stat = DIR_UP;
        p1 = QPoint(i,j-1);
        p2 = QPoint(i,j-2);
    }
    else if(event->key() == Qt::Key_Left) //点击了向左
    {
        hero_stat = DIR_LEFT;
        p1 = QPoint(i-1,j);
        p2 = QPoint(i-2,j);
    }
    else if(event->key() == Qt::Key_Down) //点击了向下
    {
        hero_stat = DIR_DOWN;
        p1 = QPoint(i,j+1);
        p2 = QPoint(i,j+2);
    }
    else if(event->key() == Qt::Key_Right) //点击了向右
    {
        hero_stat = DIR_RIGHT;
        p1 = QPoint(i+1,j);
        p2 = QPoint(i+2,j);
    }
    else {
        return QWidget::keyPressEvent(event);
    }
    if(tryGo(p1,p2))
    {
        moveTimes ++;
    }
    // 判断游戏当前状况是否获胜
    if(GameIsWin())
    {
        isWin = true;
        QMessageBox::information(this,"提示信息","恭喜过关！");
        initLevel(levelindex+1);
    }
    // 重绘地图
    update();
}

bool qpushbox::GameIsWin()
{
    for(int i = 0 ; i < 16; i++)
     {
         for(int j = 0 ; j < 16 ; j++)
         {
             if((this->gameArray[i][j]==2&&this->posArray[i][j]!=3) ||//有陷阱并且没有箱子
                ((this->gameArray[i][j]==5&&this->posArray[i][j]!=3))) //箱子与陷阱重合并且没有箱子
                {
                    return false;
                }
         }
    }
    return true; //每个陷阱都有箱子对应 返回true
}


